#pragma once
#include<iostream>
#include<unistd.h>
#include<pthread.h>
#include<vector>
#include"Sem.hpp"
using namespace std;
#define DefaultValue 5
template<class T>
class RingQueue{
  public:
  RingQueue(int num=DefaultValue)
  :_num(num)
  ,_rq(num)
  ,_pstep(0)
  ,_cstep(0)
  ,_space_sem(num)
  ,_data_sem(0)
  {
    pthread_mutex_init(&_p_mutex,nullptr);
    
    pthread_mutex_init(&_c_mutex,nullptr);
  }
  void Push(const T& in)
  {
        _space_sem.P();//申请信号量
        pthread_mutex_lock(&_p_mutex);//加锁
        _rq[_pstep++]=in;
        _pstep%=_num;
        pthread_mutex_unlock(&_p_mutex);//解锁
        _data_sem.V();
  }
  void Pop(T* out)
  {
    _data_sem.P();//申请信号量
    pthread_mutex_lock(&_c_mutex);//加锁
    *out=_rq[_cstep++];
    _cstep%=_num;
    pthread_mutex_unlock(&_c_mutex);//解锁
    
    _space_sem.V();

  }

  ~RingQueue()
  {
    pthread_mutex_destroy(&_p_mutex);
    pthread_mutex_destroy(&_c_mutex);

  }
  private:
  vector<T> _rq;//循环队列
  int _num;//最大容量
  int _pstep;//生产下标
  int _cstep;//消费下标
  Sem _space_sem;//生产者信号量
  Sem _data_sem;//消费者信号量
  pthread_mutex_t _p_mutex;
  pthread_mutex_t _c_mutex;
  

};